//
//  UILabel+Async.m
//  testtest
//
//  Created by liboxiang on 2019/3/2.
//  Copyright © 2019 liboxiang. All rights reserved.
//

#import "UILabel+Async.h"
#import <objc/runtime.h>
#import "LBXAsyncForMainThreadManager.h"

static NSString * AsyncText = @"AsyncText";
static NSString * AsyncAttributedText = @"AsyncAttributedText";
static NSString * CurrentShowAttributedText = @"CurrentShowAttributedText";

@implementation UILabel (Async)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // When swizzling a class method, use the following:
        // Class aClass = object_getClass((id)self);
        
        SEL originalSelector = @selector(drawTextInRect:);
        SEL swizzledSelector = @selector(drawAsyncTextInRect:);
        
        [self swizzleMethods:[self class] originalSelector:originalSelector swizzledSelector:swizzledSelector];
    });
}

+ (void)swizzleMethods:(Class)class originalSelector:(SEL)origSel swizzledSelector:(SEL)swizSel {
    
    Method originalMethod = class_getInstanceMethod(class, origSel);
    Method swizzledMethod = class_getInstanceMethod(class, swizSel);
    //如果实现了viewWillAppear:方法，didAddMethod为NO，否则是YES
    BOOL didAddMethod =
    class_addMethod(class,
                    origSel,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(class,
                            swizSel,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

- (void)drawAsyncTextInRect:(CGRect)rect {
    if ([self asyncAttributedText].length) {
        self.layer.contentsGravity = kCAGravityResizeAspect;
        NSAttributedString *attributeStr = self.asyncAttributedText;
        __weak typeof(self) weakSelf = self;
        
        NSMutableAttributedString *attributeKey = [[NSMutableAttributedString alloc] initWithAttributedString:[self asyncAttributedText]];
        [attributeKey appendAttributedString:[[NSAttributedString alloc] initWithString:NSStringFromCGSize(rect.size)]];
        
        [[LBXAsyncForMainThreadManager shareInstance] lbx_asyncBlock:^id{
//            UIGraphicsBeginImageContext(rect.size);
            UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
            [attributeStr drawWithRect:rect options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine context:nil];
            __block UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            return image;
        } withKey:attributeKey bindingObj:self priority:0 completionBlock:^(id  _Nonnull object) {
            UIImage *image = (UIImage *)object;
            weakSelf.layer.contents = (id)image.CGImage;
        }];
        self.layer.contents = NULL;
    }
    else {
        [self drawAsyncTextInRect:rect];
    }
}

- (void)setAsyncText:(NSString *)asyncText {
    NSAttributedString *attributeStr = [[NSAttributedString alloc] initWithString:asyncText attributes:@{NSFontAttributeName:self.font,NSForegroundColorAttributeName:self.textColor,NSBackgroundColorAttributeName:self.backgroundColor}];
    [self setAsyncAttributedText:attributeStr];
}

- (NSString *)asyncText {
    return [self asyncAttributedText].string;
}

- (void)setAsyncAttributedText:(NSAttributedString *)asyncAttributedText {
    objc_setAssociatedObject(self, (__bridge const void*)AsyncAttributedText, asyncAttributedText, OBJC_ASSOCIATION_COPY);
    [self setNeedsDisplay];
}

- (NSAttributedString *)asyncAttributedText {
    return objc_getAssociatedObject(self, (__bridge const void*)AsyncAttributedText);
}

@end
